home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Magazin: Amiga-CD 1997 November & December
/
Amiga-CD 1997 #11-12.iso
/
pd-disketten
/
ungepackt
/
4_96
/
apd-4-96-2
/
gut gekurvt
/
drawbezier.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1996-03-13
|
5KB
|
188 lines
// Beispiel 3: Beziers zeichnen
// Die eleganteste Möglichkeit, Béziers zu zeichnen ist:
// Klicken und ziehen, um die Linie zu zeichnen, dann wieder Klicken und ziehen,
// um jeweils einen Stützpunkt zu zeichnen.
#include <stdio.h>
#include <exec/types.h>
#include <intuition/intuition.h>
#include <graphics/gfx.h>
#include <graphics/rastport.h>
#include <graphics/gfxmacros.h>
#include <pragma/intuition_lib.h>
#include <pragma/exec_lib.h>
#include <pragma/graphics_lib.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stream.h>
double Bezier(struct RastPort *, double,double,double,double,double,double,double,double,double,int);
void SetPoints(int status, int x,int y,
double &k1x, double &k1y, double &k2x, double &k2y, double &k3x, double &k3y, double &k4x, double &k4y);
struct Screen *scn = OpenScreenTags(NULL,
SA_Depth, 2,
SA_Width, 640,
SA_Height, 523,
SA_Quiet, TRUE,
SA_Type, CUSTOMSCREEN|AUTOSCROLL,
SA_DisplayID, PAL_MONITOR_ID|HIRESLACE_KEY,
TAG_END);
struct Window *win = OpenWindowTags(NULL,
WA_Flags, WFLG_ACTIVATE|WFLG_CLOSEGADGET|WFLG_DEPTHGADGET|WFLG_DRAGBAR|
WFLG_NOCAREREFRESH|WFLG_SIMPLE_REFRESH|
WFLG_DEPTHGADGET|WFLG_REPORTMOUSE,
WA_Top, 11,
WA_Width, 640, WA_Height, 512,
WA_Left, 0,
WA_IDCMP, IDCMP_CLOSEWINDOW|IDCMP_MOUSEBUTTONS|IDCMP_MOUSEMOVE,
WA_CustomScreen, scn,
WA_MouseQueue, 1,
WA_BlockPen, 4, WA_DetailPen, 3,
WA_Title, "Bezier-Kurven",
TAG_END);
struct RastPort *rp = win->RPort;
char buf[255];
int status = 0;
void main() {
if(!win || !scn) { CloseWindow(win); CloseScreen(scn); return };
try {
int mbpressed=FALSE, mmoved;
char buf[50];
int zaehler = 0;
int mcx, mcy;
double k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y;
while(1) {
// Mausabfrage auf die Hardcore-Art; heute: Message-Cracking,
// Eigene Funktionen... doch hier nur ein Traum
Wait(1 << win->UserPort->mp_SigBit);
struct IntuiMessage *imsg, icpy;
mmoved = FALSE;
while(imsg = (struct IntuiMessage*)GetMsg(win->UserPort)) {
icpy = *imsg;
ReplyMsg((struct Message*)imsg);
mmoved = FALSE;
switch(icpy.Class) {
case IDCMP_CLOSEWINDOW:
throw(int(1)); // kein guter Stil, aber einfach...
break;
case IDCMP_MOUSEBUTTONS:
if(icpy.Code == SELECTDOWN) {
mbpressed=TRUE;
SetDrMd(rp,JAM2|COMPLEMENT);
SetAPen(rp,2);
if(status)
Bezier(rp,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y,25,1);
SetPoints(status,icpy.MouseX,icpy.MouseY,
k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y);
Bezier(rp,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y,25,1);
sprintf(buf, "%1d (%3d,%3d), Pressed", status, icpy.MouseX,icpy.MouseY);
SetWindowTitles(win,buf,(STRPTR)-1);
if(status<2) status++;
} else if(icpy.Code == SELECTUP){
mbpressed = FALSE;
Bezier(rp,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y,25,1);
SetPoints(status,icpy.MouseX,icpy.MouseY,
k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y);
Bezier(rp,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y,25,1);
if(status == 3) {
Bezier(rp,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y,25,1);
SetDrMd(rp, JAM2);
SetAPen(rp, 1);
Bezier(rp,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y,100,0);
}
status=(status+1)%4;
sprintf(buf, "%1d (%3d,%3d), ", status, icpy.MouseX,icpy.MouseY);
SetWindowTitles(win,buf,(STRPTR)-1);
}
break;
case IDCMP_MOUSEMOVE:
mmoved = TRUE;
mcx = icpy.MouseX;
mcy = icpy.MouseY;
}
}
if(mmoved && mbpressed) {
sprintf(buf, "%1d (%3d,%3d), Moved Pressed", status, mcx,mcy);
SetWindowTitles(win,buf,(STRPTR)-1);
Bezier(rp,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y,25,1);
SetPoints(status,mcx,mcy,
k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y);
Bezier(rp,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y,25,1);
}
}
} catch(int n) {
if(n>1) cout << "Fehler "<< n << "\n";
CloseWindow(win); CloseScreen(scn); return;
}
}
void SetPoints(int status, int x, int y,
double &k1x, double &k1y, double &k2x, double &k2y, double &k3x, double &k3y, double &k4x, double &k4y)
{
switch(status) {
case 0: // Erster Fixpunkt
k1x=k2x=k3x=k4x = x;
k1y=k2y=k3y=k4y = y;
break;
case 1: // Zweiter Fixpunkt
k3x=k4x = x;
k3y=k4y = y;
break;
case 2: // erster Kontrollpunkt
k2x=x;
k2y=y;
break;
case 3: // zweiter
k3x=x;
k3y=y;
break;
}
sprintf(buf, "s: %d; (%3.1f,%3.1f),(%3.1f,%3.1f),(%3.1f,%3.1f),(%3.1f,%3.1f)",status,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y);
SetWindowTitles(win, (STRPTR)-1, buf);
}
struct Point {
int x;
int y;
};
double Bezier(struct RastPort *rp,
double k0x,double k0y,double k1x,double k1y,
double k2x,double k2y,double k3x,double k3y, double nr,int flag)
{
const double range =
floor(10+(fabs(k0y-k1y)+fabs(k0x-k1x)+fabs(k1x-k2x)+
fabs(k1y-k2y)+fabs(k2x-k3x)+fabs(k2y-k3y))/30.0);
const double step = 1.0/range;
double bx, by, emt, emt2, t2, tm3, emtm3;
const double rst = range*step;
Move(rp,(long)k0x,(long)k0y);
for(double t = step; t <= rst; t+= step)
{
emt = 1-t; emt2=emt*emt; t2=t*t; tm3=3*t; emtm3 = 3*emt;
bx = emt2*(emt*k0x + tm3*k1x) + t2*(emtm3*k2x + t*k3x);
by = emt2*(emt*k0y + tm3*k1y) + t2*(emtm3*k2y + t*k3y);
Draw(rp,(long)bx,(long)by);
}
return range;
}